﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace DbUpdateManageSql
{
    /// <summary>
    /// 对比结果
    /// </summary>
    public enum ContrastResult
    {
        [Description("没有")]
        No = 0,
        [Description("有")]
        Yes,
        [Description("异常")]
        Unusual,

    }
  
    public class DbColumnAttribute : Attribute
    {
        public string Content { get; set; }
        public DbColumnAttribute(string dbType)
        {
            IsNullable = true;
            DbType = dbType;
        }
        public DbColumnAttribute(string dbType, bool isPrimaryKey) : this(dbType)
        {
            IsPrimaryKey = isPrimaryKey;
        }
        public DbColumnAttribute(string dbType, int length) : this(dbType)
        {
            Length = length;
        }
        public DbColumnAttribute(string dbType, int length, int scale) : this(dbType, length)
        {
            Scale = scale;
        }
        public DbColumnAttribute(string dbType, int length, int scale, bool isIdentity) : this(dbType, scale, length)
        {
            IsIdentity = isIdentity;
        }
        //public DbColumnAttribute(string dbType, int length, int scale, bool isIdentity, bool isNullable) : this(dbType, length, scale, isIdentity)
        //{
        //    IsNullable = isNullable;
        //}
        //public DbColumnAttribute(string dbType, int length, int scale, bool isIdentity, bool isPrimaryKey, bool isNullable) : this(dbType, length, scale, isIdentity, isPrimaryKey)
        //{
        //    IsPrimaryKey = isPrimaryKey;
        //}

        public DbColumnAttribute(string dbType = "varchar", int length = 50, int scale = 0, bool isIdentity = false, bool isPrimaryKey = false, bool isNullable = true) : this(dbType, length, scale, isIdentity)
        {
            IsPrimaryKey = isPrimaryKey;
            IsNullable = isNullable;
        }

        public string GetTypeAll()
        {
            string type;
            switch (DbType.ToLower())
            {
                case "int":
                    type = DbType;
                    if (IsIdentity)
                        type += " identity";

                    break;
                case "char":
                case "varchar":
                case "nchar":
                case "nvarchar":
                    if (Length == 0)
                        type = DbType + "(50)";
                    else
                        type = DbType + "(" + Length + ")";
                    break;
                case "decimal":
                    if (Length == 0)
                        type = "decimal(18,2)";
                    else
                        type = "decimal(" + Length + "," + Scale + ")";
                    break;

                default:
                    type = DbType + (IsNullable ? " null" : " not null");
                    break;
            }
            if (IsPrimaryKey)
                type += " not null";
            return type;
        }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public string DbType { get; set; }
        /// <summary>
        /// 长度
        /// </summary>
        public int Length { get; set; }
        /// <summary>
        /// 小数位
        /// </summary>
        public int Scale { get; set; }
        /// <summary>
        /// 是否主键
        /// </summary>
        public bool IsPrimaryKey { get; set; }

        /// <summary>
        /// 是否自增列
        /// </summary>
        public bool IsIdentity { get; set; }
        /// <summary>
        /// 是否允许空
        /// </summary>
        public bool IsNullable { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Remark { get; set; }
    }

    /// <summary>
    /// 表结构
    /// </summary>
    public sealed class DbTable
    {
        /// <summary>
        /// 表名称
        /// </summary>
        public string TableName { get; set; }
        /// <summary>
        /// 表的架构
        /// </summary>
        public string SchemaName { get; set; }
        /// <summary>
        /// 表的记录数
        /// </summary>
        public int Rows { get; set; }
        /// <summary>
        /// 是否含有主键
        /// </summary>
        public bool HasPrimaryKey { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Remark { get; set; }
        /// <summary>
        /// 对比
        /// </summary>
        public ContrastResult Contrast { get; set; }
        /// <summary>
        /// 列数据
        /// </summary>
        public List<DbColumn> Column { get; set; }
    }

    /// <summary>
    /// 表字段结构
    /// </summary>
    public sealed class DbColumn
    {
        /// <summary>
        /// 字段ID
        /// </summary>
        public int ColumnId { get; set; }

        /// <summary>
        /// 是否主键
        /// </summary>
        public bool IsPrimaryKey { get; set; }

        /// <summary>
        /// 字段名称
        /// </summary>
        public string ColumnName { get; set; }

        /// <summary>
        /// 数据类型
        /// </summary>
        public string DbType { get; set; }

        /// <summary>
        /// 数据类型全部
        /// </summary>
        public string DbTypeAll { get; set; }
        //   _cSharpType = SqlServerDbTypeMap.MapCsharpType(_DbType);

        /// <summary>
        /// 数据库类型对应的C#类型
        /// </summary> 
        public string CSharpType { get; set; }

        ///// <summary>
        ///// 
        ///// </summary>
        //public Type CommonType
        //{
        //    get
        //    {
        //        return SqlServerDbTypeMap.MapCommonType(DbType);
        //    }
        //}

        /// <summary>
        /// 字节长度
        /// </summary>
        public int ByteLength { get; set; }

        /// <summary>
        /// 字符长度
        /// </summary>
        public int CharLength { get; set; }

        /// <summary>
        /// 小数位
        /// </summary>
        public int Scale { get; set; }

        /// <summary>
        /// 是否自增列
        /// </summary>
        public bool IsIdentity { get; set; }

        /// <summary>
        /// 是否允许空
        /// </summary>
        public bool IsNullable { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string Remark { get; set; }
        /// <summary>
        /// 对比
        /// </summary>
        public ContrastResult Contrast { get; set; }


    }



    public class SqlServerDbTypeMap
    {
        public static string MapCsharpType(string dbtype)
        {
            if (string.IsNullOrEmpty(dbtype)) return dbtype;
            dbtype = dbtype.ToLower();
            string csharpType;
            switch (dbtype)
            {
                case "bigint": csharpType = "long"; break;
                case "binary": csharpType = "byte[]"; break;
                case "bit": csharpType = "bool"; break;
                case "char": csharpType = "string"; break;
                case "date": csharpType = "DateTime"; break;
                case "datetime": csharpType = "DateTime"; break;
                case "datetime2": csharpType = "DateTime"; break;
                case "datetimeoffset": csharpType = "DateTimeOffset"; break;
                case "decimal": csharpType = "decimal"; break;
                case "float": csharpType = "double"; break;
                case "image": csharpType = "byte[]"; break;
                case "int": csharpType = "int"; break;
                case "money": csharpType = "decimal"; break;
                case "nchar": csharpType = "string"; break;
                case "ntext": csharpType = "string"; break;
                case "numeric": csharpType = "decimal"; break;
                case "nvarchar": csharpType = "string"; break;
                case "real": csharpType = "Single"; break;
                case "smalldatetime": csharpType = "DateTime"; break;
                case "smallint": csharpType = "short"; break;
                case "smallmoney": csharpType = "decimal"; break;
                case "sql_variant": csharpType = "object"; break;
                case "sysname": csharpType = "object"; break;
                case "text": csharpType = "string"; break;
                case "time": csharpType = "TimeSpan"; break;
                case "timestamp": csharpType = "byte[]"; break;
                case "tinyint": csharpType = "byte"; break;
                case "uniqueidentifier": csharpType = "string"; break;
                case "varbinary": csharpType = "byte[]"; break;
                case "varchar": csharpType = "string"; break;
                case "xml": csharpType = "string"; break;
                default: csharpType = "object"; break;
            }
            return csharpType;
        }

        public static string MapCsharpDb(string dbtype)
        {
            if (string.IsNullOrEmpty(dbtype)) return dbtype;
            dbtype = dbtype.ToLower();
            string csharpType;
            switch (dbtype)
            {
                case "long": csharpType = "bigint"; break;
                case "byte[]": csharpType = "binary"; break;

                case "bool": csharpType = "bit"; break;
                // case "string": csharpType = "char"; break;
                //  case "DateTime": csharpType = "date"; break;
                case "DateTime": csharpType = "datetime"; break;
                //   case "DateTime": csharpType = "datetime2"; break;
                case "DateTimeOffset": csharpType = "datetimeoffset"; break;
                case "decimal": csharpType = "decimal"; break;
                case "double": csharpType = "float"; break;
                //  case "byte[]": csharpType = "image"; break;
                case "int": csharpType = "int"; break;
                //  case "decimal": csharpType = "money"; break;
                //  case "string": csharpType = "nchar"; break;
                //  case "string": csharpType = "ntext"; break;
                // case "decimal": csharpType = "numeric"; break;
                //   case "string": csharpType = "nvarchar"; break;
                case "Single": csharpType = "real"; break;
                //   case "DateTime": csharpType = "smalldatetime"; break;
                case "short": csharpType = "smallint"; break;
                // case "decimal": csharpType = "smallmoney"; break;
                //  case "object": csharpType = "sql_variant"; break;
                case "object": csharpType = "sysname"; break;
                // case "string": csharpType = "text"; break;
                case "TimeSpan": csharpType = "time"; break;
                //  case "byte[]": csharpType = "timestamp"; break;
                case "byte": csharpType = "tinyint"; break;
                //   case "string": csharpType = "uniqueidentifier"; break;
                //   case "byte[]": csharpType = "varbinary"; break;
                //    case "string": csharpType = "varchar"; break;
                //   case "string": csharpType = "xml"; break;

                default: csharpType = "nvarchar"; break;
            }
            return csharpType;
        }

        public static Type MapCommonType(string dbtype)
        {
            if (string.IsNullOrEmpty(dbtype)) return Type.Missing.GetType();
            dbtype = dbtype.ToLower();
            Type commonType;
            switch (dbtype)
            {
                case "bigint": commonType = typeof(long); break;
                case "binary": commonType = typeof(byte[]); break;
                case "bit": commonType = typeof(bool); break;
                case "char": commonType = typeof(string); break;
                case "date": commonType = typeof(DateTime); break;
                case "datetime": commonType = typeof(DateTime); break;
                case "datetime2": commonType = typeof(DateTime); break;
                case "datetimeoffset": commonType = typeof(DateTimeOffset); break;
                case "decimal": commonType = typeof(decimal); break;
                case "float": commonType = typeof(double); break;
                case "image": commonType = typeof(byte[]); break;
                case "int": commonType = typeof(int); break;
                case "money": commonType = typeof(decimal); break;
                case "nchar": commonType = typeof(string); break;
                case "ntext": commonType = typeof(string); break;
                case "numeric": commonType = typeof(decimal); break;
                case "nvarchar": commonType = typeof(string); break;
                case "real": commonType = typeof(Single); break;
                case "smalldatetime": commonType = typeof(DateTime); break;
                case "smallint": commonType = typeof(short); break;
                case "smallmoney": commonType = typeof(decimal); break;
                case "sql_variant": commonType = typeof(object); break;
                case "sysname": commonType = typeof(object); break;
                case "text": commonType = typeof(string); break;
                case "time": commonType = typeof(TimeSpan); break;
                case "timestamp": commonType = typeof(byte[]); break;
                case "tinyint": commonType = typeof(byte); break;
                case "uniqueidentifier": commonType = typeof(string); break;
                case "varbinary": commonType = typeof(byte[]); break;
                case "varchar": commonType = typeof(string); break;
                case "xml": commonType = typeof(string); break;
                default: commonType = typeof(object); break;
            }
            return commonType;
        }
    }



}
